package com.heartbeat.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;


public class BaseDao {
	private final static Logger logger = Logger.getLogger(BaseDao.class);

	/**
	 * 用来执行update, insert, delete等sql语句，区别于pojo
	 * 
	 * @param sql 将要执行的sql，包括update,insert,delete语句
	 * @return sql是否执行成功
	 */
	public boolean executeUpdateBySql(String sql) {
		Session sn = null;
		boolean isSucced = false;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			Connection conn = sn.connection();
			conn.createStatement().executeUpdate(sql);
			ts.commit();
			isSucced = true;
		} catch (Exception e) {
			logger.error("executeUpdateBySql :" + e.getMessage(), e);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return isSucced;
	}
	
		
	public boolean save(final Object entity) {
		try {
			Session sn = null;
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			Object obj = sn.save(entity);
			ts.commit();
			
			if(obj!=null){
				return true;
			}
		} catch (Exception ex) {
			logger.error("save() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		
		return false;
	}
	
	 public Object save(final Object entity, boolean returnId) {
		try {
			Session sn = null;
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			Object obj = sn.save(entity);
			ts.commit();
			
			if(returnId){
				return obj;
			}
		} catch (Exception ex) {
			logger.error("save() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		
		return null;
	}
	
	public void saveOrUpdate(final Object entity) {
		try {
			Session sn = null;
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			sn.saveOrUpdate(entity);
			ts.commit();
		} catch (Exception ex) {
			logger.error("save() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}

	public void update(final Object entity) {
		Session sn = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			sn.update(entity);
			ts.commit();
		} catch (Exception ex) {
			logger.error("update() error:" + ex.getMessage(), ex);
		} finally {
//			HibernateSessionFactory.closeSession();
			if(sn!=null)
				sn.close();
		}
	}

	public int delete(final Object entity) {
		Session sn = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			sn.delete(entity);
			ts.commit();
		} catch (Exception ex) {
			logger.error("delete() error:" + ex.getMessage(), ex);
			return -1;
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return 1;
	}

	public Object get(final Class entity, final Serializable id) {
		Session sn = null;
		Object obj = null;
		try {
			sn = HibernateSessionFactory.getSession();
			 Transaction ts = sn.beginTransaction();
			obj = sn.get(entity, id);
		} catch (Exception ex) {
			logger.error("get() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return obj;
	}

	public List findAll(final Class entity) {
		Session sn = null;
		List list = null;
		try {
			sn = HibernateSessionFactory.getSession();
			// Transaction ts = sn.beginTransaction();
			list = sn.createQuery(" from " + entity.getName()).list();
			// ts.commit();
		} catch (Exception ex) {
			logger.error("find() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return list;
	}
	
	public List findByPage(final String query, int step, int firstResult) {
		Session sn = null;
		List list = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			list = sn.createQuery(query).setFirstResult(firstResult).setMaxResults(step).list();
			 ts.commit();
		} catch (Exception ex) {
			logger.error("find() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return list;
	}

	public List find(final String query) {
		Session sn = null;
		List list = null;
		try {
			sn = HibernateSessionFactory.getSession();
			// Transaction ts = sn.beginTransaction();
			list = sn.createQuery(query).list();
			// ts.commit();
		} catch (Exception ex) {
			logger.error("find() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return list;
	}

	public List find(final String queryStr, final Object[] parameter) {
		Session sn = null;
		List list = null;
		try {
			sn = HibernateSessionFactory.getSession();
			// Transaction ts = sn.beginTransaction();
			Query query = sn.createQuery(queryStr);
			int len = parameter.length;
			for (int i = 0; i < len; i++) {
				query.setParameter(i, parameter[i]);
			}
			list = query.list();

			// ts.commit();
		} catch (Exception ex) {
			logger.error("find error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return list;
	}

	/**
	 * 得到分页的结�?
	 * 
	 * @param currentPage :
	 *            当前�?
	 * @param pageSize :
	 *            每页要显示多少条数据
	 * @param countSql :
	 *            统计Hql
	 * @param countValues :
	 *            统计Hql中的�?(是一个对象数�?)
	 * @param sql
	 * @param values
	 * @return
	 */
	public HashMap getPageResult(int currentPage, final int pageSize,
			final String countHql, final Object[] countValues,
			final String hql, final Object[] values) {

		HashMap map = new HashMap();
		List list = new ArrayList();

		int totalSize = getTotalSize(countHql, countValues);

		int start = 0; // 第currentPage页数据是从哪条记录开始的
		int end = 0; // 第currentPage页数据是从哪条记录结束的
		int totalPage = 0;

		/**
		 * *** 找出当前要显示页(currentpage)的开始记录号"start"和结束记录号"end",以便只把当前页的数据给找出来
		 * *****
		 */
		totalPage = (int) Math.ceil((double) totalSize / pageSize); // 共有多少�?
		// System.out.println("total:"+total+" totalPage:"+totalPage+"
		// currentPage:"+currentPage);
		// 如果当前页大于�?�页�?,则显示最后一�?
		if (currentPage > totalPage)
			currentPage = totalPage;
		// 如果当前页小�?0,则显示第�?�?
		if (currentPage < 1)
			currentPage = 1;

		// 根据条件判断，取出所�?记录
		start = pageSize * (currentPage - 1);
		end = start + pageSize;
		if (end > totalSize)
			end = totalSize; // 因为在下面的循环中用到的是小�?,�?以在此用"="

		list = getCurrentPageResult(start, pageSize, hql, values);

		map.put("list", list);
		map.put("currentPage", String.valueOf(currentPage));
		map.put("totalPage", String.valueOf(totalPage));
		map.put("pageSize", String.valueOf(pageSize));
		map.put("totalSize", String.valueOf(totalSize));

		return map;

	}
		
	private int getTotalSize(String countHql, Object[] countValues) {
		Session session = HibernateSessionFactory.getSession();
		Query query = session.createQuery(countHql);

		if (countValues != null) {
			for (int i = 0; i < countValues.length; i++) {
				String type = getType(countValues[i].getClass().getName());
				if (type.equals("String")) {
					query.setString(i, "%" + countValues[i].toString() + "%");
				} else if (type.equals("Date")) {
					query.setDate(i, (Date) countValues[i]);
				} else if (type.equals("Integer")) {
					query.setInteger(i, ((Integer) countValues[i]).intValue());
				} else if (type.equals("Boolean")) {
					query.setBoolean(i, ((Boolean) countValues[i]).booleanValue());
				}
			}
		}
		return ((Integer) query.uniqueResult()).intValue();
	}

	/**
	 * 功能:得到分页的结�?(当前�?)
	 * 
	 * @param start :
	 *            �?始记录号
	 * @param pageSize :
	 *            每页显示多少条记�?
	 * @param sql :
	 *            要查询的sql语句
	 * @param values :
	 *            sql语句中的变量�?
	 * @return
	 */
	public List getCurrentPageResult(final int start, final int pageSize,
			final String sql, final Object[] values) {

		Session session = HibernateSessionFactory.getSession();

		Query query = session.createQuery(sql);

		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				String type = getType(values[i].getClass().getName());
				if (type.equals("String")) {
					query.setString(i, "%" + values[i].toString() + "%");
				} else if (type.equals("Date")) {
					query.setDate(i, (Date) values[i]);
				} else if (type.equals("Integer")) {
					query.setInteger(i, ((Integer) values[i]).intValue());
				} else if (type.equals("Boolean")) {
					query.setBoolean(i, ((Boolean) values[i]).booleanValue());
				}
			}
		}

		query.setFetchSize(30);
		query.setFirstResult(start);
		query.setMaxResults(pageSize);

		return query.list();
	}

	private String getType(String typeParam) {
		int last = typeParam.lastIndexOf(".");
		return typeParam.substring(last + 1);
	}

	/**
	 * 执行sql语句
	 * 
	 * @param sql
	 * @return List HashMap
	 * @throws YiChaAdException
	 */
	public List executeQuery(String sql) {
		Session sn = null;
		ResultSet rs = null;
		List list = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Connection conn = sn.connection();
			rs = conn.createStatement().executeQuery(sql);
			list = getList(rs);
		} catch (Exception e) {
			logger.error("executeQuery :" + e.getMessage(), e);
		} finally {
			HibernateSessionFactory.closeSession();
		}
		return list;
	}


	/*
	 * @由rs得到ArrayList
	 */
	ArrayList getList(ResultSet rs) {
		ArrayList vector = new ArrayList();
		ResultSetMetaData rsmd = null;
		HashMap map = new HashMap();
		int columnCount = 0;
		try {
			rsmd = rs.getMetaData();
			columnCount = rsmd.getColumnCount();
			String[] columnName = new String[columnCount];

			for (int i = 0; i < columnCount; i++) {
				columnName[i] = rsmd.getColumnName(i + 1);
			}
			while (rs.next()) {
				map = new HashMap();
				// System.out.println("rows:"+rs.getRow()+"
				// id:"+rs.getInt("id")+" email:"+rs.getString("email"));
				for (int i = 0; i < columnCount; i++) {
					int type = rsmd.getColumnType(i + 1);
					// System.out.println(columnName[i]+type);
					try {
						if (rs.getObject(i + 1) == null)
							map.put(columnName[i].toLowerCase(), null);
						else {
							switch (type) {
							case 4: // integer�?
								map.put(columnName[i], Integer.valueOf(rs
										.getString(i + 1)));
								break;
							case 91: // date�?
								map.put(columnName[i], rs.getDate(i + 1));
								break;
							case 93: // datetime �? timestamp
								map.put(columnName[i], (Timestamp) rs
										.getObject(i + 1));
								break;
							case -7: // boolean�?
								map.put(columnName[i], (Boolean) rs
										.getObject(i + 1));
								break;
							default:
								map.put(columnName[i], rs.getString(i + 1));
							}
						}
					} catch (Exception e) {
						map.put(columnName[i], "");
						// System.out.println("列名:"+columnName[i]+"出错!"+e.getMessage().toString());
					}
				}
				vector.add(map);
			}
		} catch (SQLException e) {
			logger.error("getList()方法出错:", e);
		}
		return vector;
	}

	
				/*********  以下部分是SQL(不是HQL)的分页实现部�? *************/
	/**
	 * 功能:得到指定页的数据
	 *  @param:countSql:查询统计(只要count(*)和where条件)  
	 *  @param:sql:查询数据
	 *  @param:	currentPage:当前是第几页
	 *  @param:	pageSize:每页显示多少条记�?
	 *  @return 
	 *   HashMap:
	 *    "totalPage":共有多少�?
	 *	  "currentPage":当前是第几页
	 *	  "list":得到的数据列�?(Vector类型)
	 */
	public HashMap getPageResult_sql(String countSql,String sql ,int currentPage,int pageSize) {
		
		Session sn = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		sn = HibernateSessionFactory.getSession();
		Connection conn = sn.connection();
	
		int total= 0;  //总共有多少条记录
		int totalPage = 0;	//共有多少�?
		
		try{
			stmt = conn.createStatement();
			rs = stmt.executeQuery(countSql);
			if (rs.next()) 
				total = rs.getInt(1); 
		}catch(SQLException e){
			logger.error("执行分页getPageResultSet()在得到�?�页数时出错:"+countSql,e);
		}
	
		
		// 设置当前页数和�?�页�? 
		totalPage = (int)Math.ceil((double)total/pageSize);   //共有多少�? 	

		if(currentPage<1) currentPage=1;
		//如果当前页大于�?�页�?,则显示最后一�?
		if(currentPage>totalPage) currentPage = totalPage;
		//如果当前页小�?0,则显示第�?�?
		if(currentPage<1) currentPage = 1;
		
		// 根据条件判断，取出所�?记录		
		int start = pageSize*(currentPage-1);
	
		sql = sql + " LIMIT " + start + " , " + pageSize; 
		Vector vector = getResultSet_sql(sql); 
		 
		HashMap hashMap = new HashMap();
		hashMap.put("totalRecords", total);
		hashMap.put("totalPage",Integer.valueOf(totalPage));   //共有多少�?
		hashMap.put("currentPage",Integer.valueOf(currentPage));
		hashMap.put("list",vector);
		
		return hashMap;
	}
	
	private Vector getResultSet_sql(String sql) {
		Session sn = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		sn = HibernateSessionFactory.getSession();
		Connection conn = sn.connection();
		Vector vector = null;
		try{
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
			vector = getVector_sql(rs);
		}catch(SQLException e){
			logger.error("执行SQL出错:"+sql,e);
		}finally{
			HibernateSessionFactory.closeSession();				
		}
		return vector;
	}
	/*
	 * @由rs得到Vector
	 */
	private Vector getVector_sql(ResultSet rs) {
		Vector vector = new Vector();
		ResultSetMetaData rsmd = null;
		HashMap map = new HashMap();
		int columnCount = 0;
		try{
			rsmd = rs.getMetaData();
			columnCount = rsmd.getColumnCount();
			String[] columnName = new String[columnCount];
			
			for(int i=0;i<columnCount;i++){
				columnName[i]=rsmd.getColumnName(i+1);
			}
			while(rs.next()){
				map = new HashMap();
		//		System.out.println("rows:"+rs.getRow()+" id:"+rs.getInt("id")+"  email:"+rs.getString("email"));
				for(int i=0;i<columnCount;i++){
					int type = rsmd.getColumnType(i + 1);
			//		System.out.println(columnName[i]+type);
					try{
						if(rs.getObject(i+1)==null)
							map.put(columnName[i],null);
						else{
							switch (type) {
								case 4:		//integer�?
									map.put(columnName[i], Integer.valueOf(rs.getInt(i+1)) );
									break;
								case 91:	//date�?
									map.put(columnName[i],rs.getDate(i+1));
									break;				
								case 93:	//datetime �? timestamp
									map.put(columnName[i],(Timestamp)rs.getObject(i+1));
									break;
								case -7:	//boolean�?
									map.put(columnName[i],(Boolean)rs.getObject(i+1));
									break;
								default:
									map.put(columnName[i],rs.getString(i+1));
								}
						}
					}catch(Exception e){
						map.put(columnName[i],"");
						//System.out.println("列名:"+columnName[i]+"出错!"+e.getMessage().toString());
					}
					
				}
				
				vector.add(map);
			}
		}catch(SQLException e){
			logger.error("getVector()方法出错:",e);
		}
		
		return vector;
	}
	
	/**
	 * 批量修改数据
	 * 
	 * @param toUpdateList �?要更改的�?组POJO，其结构List<Object>
	 */
	public void batchUpdate(List toUpdateList){
		Session sn = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			for(int i = 0; i < toUpdateList.size(); i++){
				Object anObject = toUpdateList.get(i);
				sn.update(anObject);
			}
			ts.commit();
		} catch (Exception ex) {
			logger.error("batchUpdate() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}
	
	/**
	 * 批量插入数据
	 * 
	 * @param toSaveList �?要保存的�?组对象，其结构List<Object>
	 */
	public void batchSave(List toSaveList){
		Session sn = null;
		try {
			sn = HibernateSessionFactory.getSession();
			Transaction ts = sn.beginTransaction();
			for(int i = 0; i < toSaveList.size(); i++){
				Object anObject = toSaveList.get(i);
				sn.save(anObject);
			}
			ts.commit();
		} catch (Exception ex) {
			logger.error("batchSave() error:" + ex.getMessage(), ex);
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}
	
	/**
	 * @param entityName 实例�?
	 * @param fields 实例对应的属�?
	 * @param operator where语句里的对比操作，比�?"=, like"�?
	 * @param values where语句中属性对应的�?
	 * @return
	 */
	public List findByCriteria(String entityName, String[] fields, String[] operator, String[] values){
		String hql = " from " + entityName + " where 1=1 ";
		
		for(int i = 0; i < fields.length; i++){
			hql = hql + " and " + fields[i] + operator[i] + "'" + values[i] + "' ";
		}
		
		List searchRes = this.find(hql);
		
		return searchRes;
	}
	
	/**
	 * @param entityName 实例�?
	 * @param fields 实例对应的属�?
	 * @param operator where语句里的对比操作，比�?"=, like"�?
	 * @param values where语句中属性对应的�?
	 * @return
	 */
	public Object getObjectByCriteria(String entityName, String[] fields, String[] operator, String[] values){
		List searchRes = this.findByCriteria(entityName, fields, operator, values);
		
		if(searchRes != null && searchRes.size() > 0){
			return searchRes.get(0);
		}
		
		return null;
	}
	
	/**
	 * @param entityName 实例�?
	 * @param aField 实例对应的属�?
	 * @param aOperator where语句里的对比操作，比�?"=, like"�?
	 * @param aValue where语句中属性对应的�?
	 * @return
	 */
	public Object getObjectByOneCriteria(String entityName, String aField, String aOperator, String aValue){
		
		Object searchRes = getObjectByCriteria(entityName, new String[]{aField}, new String[]{aOperator}, new String[]{aValue});
		
		return searchRes;
	}
}
